package com.yingxin.yxerp.module.dingtalk.service.impl;

import com.yingxin.yx.framework.commons.constant.PathConst;
import com.yingxin.yx.framework.commons.exception.BizException;
import com.yingxin.yx.framework.commons.helper.PropertiesHelper;
import com.yingxin.yxerp.module.dingtalk.service.ImgService;
import com.yingxin.yxerp.module.easypoi.excel.ExcelExportUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.Version;
import lombok.extern.slf4j.Slf4j;
import org.fit.cssbox.awt.BrowserCanvas;
import org.fit.cssbox.css.CSSNorm;
import org.fit.cssbox.css.DOMAnalyzer;
import org.fit.cssbox.io.DOMSource;
import org.fit.cssbox.io.DefaultDOMSource;
import org.fit.cssbox.io.DocumentSource;
import org.fit.cssbox.io.StreamDocumentSource;
import org.fit.cssbox.layout.Dimension;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Calendar;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service
public class ImgServiceImpl implements ImgService {

    private static String filePath;

    /**
     * 数据、模板名称、图片的宽度1440、高度（一级表头40+二级表头20+表格表头20，每行 20）
     * @param map          数据
     * @param templateName 模板名称
     * @param length       数据条数
     * @throws IOException
     * @throws TemplateException
     */
    @Override
    public String htmlToImage(Map<String, Object> map, String templateName, Integer width, Integer length) {
        try {
            // 获取新模板
            String template = getTemplate(templateName, map);
            // 保存数据
            return saveFile(template, width, length);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @param map          数据
     * @param templateName 模板名称
     * @param name         文件名称
     * @return
     */
    @Override
    public String export(Map<String, Object> map, String templateName, String name){
        // 获取模版
        String path = PropertiesHelper.getInstance().getProperty(PathConst.FTL_DIR);
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        // 判断有没有该模板
        String outputFile = file.getPath() + "/" + templateName;
        File fileTemplate = new File(outputFile);
        if (!fileTemplate.exists()) {
            throw new BizException("模板未找到,请检查模板文件");
        }

        //导出的文件名
        String outPath = PropertiesHelper.getInstance().getProperty(PathConst.EXPORT_DIR)+"/excel";
        String fileName = outPath +"\\"+ ExcelExportUtil.buildFileName(name) + ".xlsx";

        // 配置模板属性
        Configuration configuration = new Configuration(new Version("2.3.0"));
        String encoding = "UTF-8";
        Writer out = null;
        try {
            configuration.setDirectoryForTemplateLoading(file);
            Template template = configuration.getTemplate(templateName);
            OutputStream outputStream = new FileOutputStream(fileName);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "utf-8");
            out = new BufferedWriter(outputStreamWriter);
            // 将填充数据填入模板文件并输出到目标文件
            template.process(map, out);
            out.flush();
            outputStream.flush();
            out.close();
            outputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (TemplateException e) {
            throw new RuntimeException(e);
        }
        return new File(fileName).getName();
    }

    @Override
    public String exportPrimaryName(Map<String, Object> map, String templateName, String name){
        // 获取模版
        String path = PropertiesHelper.getInstance().getProperty(PathConst.FTL_DIR);
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        // 判断有没有该模板
        String outputFile = file.getPath() + "/" + templateName;
        File fileTemplate = new File(outputFile);
        if (!fileTemplate.exists()) {
            throw new BizException("模板未找到,请检查模板文件");
        }

        //导出的文件名
        String outPath = PropertiesHelper.getInstance().getProperty(PathConst.EXPORT_DIR)+"/excel";
        String fileName = outPath +"\\"+ name + ".xlsx";

        // 配置模板属性
        Configuration configuration = new Configuration(new Version("2.3.0"));
        String encoding = "UTF-8";
        Writer out = null;
        try {
            configuration.setDirectoryForTemplateLoading(file);
            Template template = configuration.getTemplate(templateName);
            OutputStream outputStream = new FileOutputStream(fileName);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "utf-8");
            out = new BufferedWriter(outputStreamWriter);
            // 将填充数据填入模板文件并输出到目标文件
            template.process(map, out);
            out.flush();
            outputStream.flush();
            out.close();
            outputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (TemplateException e) {
            throw new RuntimeException(e);
        }
        return fileName;
    }


    /**
     * 获取新字符串模板
     * @param templateName
     * @return
     * @throws IOException
     */
    @Override
    public String getTemplate(String templateName, Map<String, Object> map) {
        String path = PropertiesHelper.getInstance().getProperty(PathConst.FTL_DIR);
        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }
        // 判断有没有该模板
        String outputFile = file.getPath() + "/" + templateName;
        File fileTemplate = new File(outputFile);
        if (!fileTemplate.exists()) {
           throw new BizException("模板未找到,请检查模板文件");
        }

        //模板
        String stringTemplate = "";
        Configuration configuration = new Configuration();
        String encoding = "UTF-8";
        StringWriter out_ = new StringWriter();
        try {
            configuration.setDirectoryForTemplateLoading(file);
            Template template = configuration.getTemplate(templateName,encoding);
            template.process(map, out_);
            stringTemplate = out_.getBuffer().toString();
            out_.flush();
            out_.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (TemplateException e) {
            throw new RuntimeException(e);
        }
        return  stringTemplate;
    }

    /**
     * 保存数据设置样式
     * @param stringTemplate
     * @param length 多少条数据
     * @return
     */
    @Override
    public String saveFile(String stringTemplate, Integer width, Integer length) throws IOException {
        String path = getPath(PropertiesHelper.getInstance().getProperty(PathConst.REPORT_DIR),"/Image");
        // 创建一个字节流
        InputStream is = new ByteArrayInputStream(stringTemplate.getBytes(StandardCharsets.UTF_8));
        // 创建一个文档资源
        DocumentSource docSource = new StreamDocumentSource(is, null, "text/html; charset=utf-8");
        // 创建一个文件流
        String fileName = path +"\\"+ UUID.randomUUID().toString() + ".png";
        FileOutputStream out = new FileOutputStream(fileName);
        try {
            // 解析输入文档
            DOMSource parser = new DefaultDOMSource(docSource);
            // 创建CSS解析器
            DOMAnalyzer da = new DOMAnalyzer(parser.parse(), docSource.getURL());
            // 设置样式属性
            da.attributesToStyles();
            da.addStyleSheet(null, CSSNorm.stdStyleSheet(), DOMAnalyzer.Origin.AGENT);
            da.addStyleSheet(null, CSSNorm.userStyleSheet(), DOMAnalyzer.Origin.AGENT);
            da.addStyleSheet(null, CSSNorm.formsStyleSheet(), DOMAnalyzer.Origin.AGENT);
            da.getStyleSheets();
            BrowserCanvas contentCanvas = new BrowserCanvas(da.getRoot(), da, docSource.getURL());
            contentCanvas.createLayout(new Dimension(width, length));

            // 生成png文件
            ImageIO.write(contentCanvas.getEngine().getImage(), "png", out);
        } catch (Exception e) {
            log.info("HtmlToPng Exception", e);
        } finally {
            out.close();
            is.close();
            docSource.close();
        }
        return fileName;
    }

    /**
     * 判断有无文件夹
     * @param reportDir
     * @param DirName
     * @return
     */
    private  String getPath(String reportDir,String DirName) {
        Calendar calendar = Calendar.getInstance();
        //年
        int year = calendar.get(Calendar.YEAR);
        //月
        int month = calendar.get(Calendar.MONTH) + 1;
        //日
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        String path = File.separator + File.separator + year
                + File.separator + month + File.separator + day + File.separator;
        File file = new File(reportDir+ DirName + path);
        if (!file.exists()) {
            file.mkdirs();
        }
        filePath = path;
        return file.getPath();
    }
}
